package com.blaze.framework.core.util.json;

import com.blaze.framework.core.util.exception.CheckedException;
import com.blaze.framework.core.util.uitls.DateUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * json工具类
 *
 * @author created by Zhou Zongbo on 2025/5/22.
 */
@Slf4j
public final class JsonUtil {
    private JsonUtil() {

    }

    public static ObjectMapper getObjectMapper() {
        return ObjectMapperHolder.INSTANCE;
    }


    /**
     * 对象转json
     *
     * @param obj obj
     * @return json
     */
    public static String toJsonString(Object obj) {
        try {
            return getObjectMapper().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("JSON转换失败,  {}", e.getMessage(), e);
            return StringUtils.EMPTY;
        }
    }

    /**
     * json转对象
     *
     * @param text        字符串
     * @param objectClass 对象类型
     * @param <T>         泛型
     * @return T
     */
    public static <T> T parseObject(String text, Class<T> objectClass) {
        try {
            return getObjectMapper().readValue(text, objectClass);
        } catch (JsonProcessingException e) {
            throw new CheckedException("数据转换异常", e);
        }
    }

    /**
     * json转集合
     *
     * @param text           json字符串
     * @param tTypeReference 引用类型
     * @param <T>            泛型
     * @return T  如果转换异常则返回空集合
     */
    public static <T> List<T> parseList(Object text, TypeReference<List<T>> tTypeReference) {
        try {
            if (text instanceof String) {
                return getObjectMapper().readValue((String) text, tTypeReference);
            }
            return getObjectMapper().readValue(getObjectMapper().writeValueAsString(text), tTypeReference);
        } catch (JsonProcessingException e) {
            log.error("JSON parseList转换失败,  {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }

    /**
     * map转对象
     *
     * @param map         map
     * @param objectClass 对象类型
     * @param <T>         泛型
     * @return T
     */
    public static <T> T mapToObject(Map<String, Object> map, Class<T> objectClass) {
        return getObjectMapper().convertValue(map, objectClass);
    }

    public static <T> List<T> mapToList(Map<String, Object> map, String key, TypeReference<List<T>> typeReference) {
        if (MapUtils.isEmpty(map)) {
            return Collections.emptyList();
        }
        Object o = map.get(key);
        if (o == null) {
            return Collections.emptyList();
        }

        return parseList(o, typeReference);
    }

    /**
     * 单例创建ObjectMapper
     */
    private static class ObjectMapperHolder {
        /**
         * 创建objectMapper实例
         */
        private static final ObjectMapper INSTANCE = createObjectMapper();

        /**
         * 创建objectMapper实例
         *
         * @return ObjectMapper
         */
        private static ObjectMapper createObjectMapper() {
            ObjectMapper mapper = new ObjectMapper();
            // 序列化
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
            mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
            mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            // java 日期序列化和反序列化
            mapper.registerModule(createDateTimeModule());
            mapper.setDateFormat(new SimpleDateFormat(DateUtil.YMD_HMS.getPattern()));
            return mapper;
        }

        /**
         * 创建时间日期模块
         *
         * @return datetime module
         */
        private static SimpleModule createDateTimeModule() {
            DateTimeFormatter dateTimeFormatter = DateUtil.YMD_HMS.getDateTimeFormatter();
            DateTimeFormatter dateFormatter = DateUtil.YMD.getDateTimeFormatter();
            DateTimeFormatter timeFormatter = DateUtil.HMS.getDateTimeFormatter();
            SimpleModule module = new SimpleModule("Java8DateTimeModule");
            module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
            module.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
            module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));
            module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
            module.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
            module.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
            return module;
        }
    }
}
